成品:

成品網址
成品功能:
1.會呈現表面上的各種資訊 大頭貼/profile 連結/Repo 數量/追蹤者數量/公司/Blog/地點/何時加入等
2.跳顯示警告,如果沒找到資訊
3.顯示最新的 Repo 在下方(最多五筆)
4.Repo 以及 Profile 會是有超連結的
HTML
html 程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
   | <html lang="en">
  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <link rel="stylesheet" href="https://bootswatch.com/4/litera/bootstrap.min.css">     <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>     <title>GitHub Finder</title> </head>
  <body>     <nav class="navbar navbar-dark bg-primary mb-3">         <div class="container">             <a href="#" class="navbar-brand">GitHub Finder</a>         </div>     </nav>     <div class="container searchContainer">         <div class="search card card-body">             <h1>Search GitHub Users</h1>             <p class="lead">Enter a username to fetch a user profile and repos</p>             <div id="alert"></div>             <input type="text" id="searchUser" class="form-control" placeholder="GitHub Username...">         </div>         <br>         <div id="profile">
 
              <h3 class="page-heading mb-3">Latest Repos</h3>             <div id="repos"></div>         </div>         <div id="123"></div>     </div>
      <footer class="mt-5 p-3 text-center bg-light">         GitHub Finder ©     </footer>
      
      </script>     <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js"         integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous">     </script>     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"         integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous">     </script>
      <script src="script.js"></script>     
 
 
  </body>
  </html>
   | 
CSS:
本篇使用 bootstrap
JS:
本篇最大阻礙一直在阻擋存取 API 非常麻煩!
{“message”:”API rate limit exceeded for 36.225.127.59. (But here’s the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)”,”documentation_url”:”https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting"}
主要的 ajax 屬性參考
jQuery.ajax
functions:
- getInputValue() -把從 input 取得的內容丟進去 AJAX 內部取得 user 資料
 - getUserData() - 使用 jQuery AJAX 取得 profile 區域的資料
 - getRepoData() - 使用 jQuery AJAX 取得 Repo 區域的資料並且把它們推到 DOM 上
 - pushElToProfile() -把取得 profile 區域的資料推到 DOM 上
 
單純使用 keyup 事件把 input 的值推進去 getUserData,getRepoData 去做 AJAX
getUserData()
取得要操作的 url 使用變數的方式改變 username 為 input 去抓取 API 資料,
當成功後處理抓取到的陣列並指派給空的 obj 把它們的屬性一一取出並且指派,並且在此呼叫pushElToProfile()並且把指派的變數放入
getRepoData()
跟上方抓取使用者資料很像,但是這邊不指派給變數而是直接把取得的 API 資料(是陣列形式)做 forEach 處理當傳輸成功時直接把屬性推入 DOM 裡面,因為一次要印出五筆資料必須這樣操作。
當資料傳輸失敗則會跑判斷是判斷 status 是甚麼,給予因應的 msg,並且設置三秒後會移除
pushElToProfile()
把剛剛指派的 obj 的屬性推上去 DOM
JS 完整程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
   |  function getInputValue() {     const searchUser = $("#searchUser");
      searchUser.keyup(function () {         getUserData($(this).val());         getRepoData($(this).val());     }); }
  getInputValue();
 
  function getUserData() {     let username = $("#searchUser").val();     let url = `https://api.github.com/users/${username}`;     $.ajax({         type: "GET",         url: url,         dataType: "json",         success: function (res) {             let obj = {};             obj.avatar_url = res.avatar_url || "no data";             obj.profile_url = res.html_url || "no data";             obj.public_gists = res.public_gists || "no data";             obj.public_repos = res.public_repos || "no data";             obj.followers = res.followers || "no data";             obj.following = res.following || "no data";             obj.company = res.company || "no data";             obj.location = res.location || "no data";             obj.blog = res.blog || "no data";             obj.create_at = res.created_at || "no data";                          pushElToProfile(obj);         },     }); }
  function getRepoData() {     let username = $("#searchUser").val();     let url = `https://api.github.com/users/${username}/repos?per_page=5&sort=created: asc `;     $.ajax({         type: "GET",         url: url,         dataType: "json",
                   error: function (jqXHR, exception) {             var msg = "";             if (jqXHR.status === 0) {                 msg = "Not connect.\n Verify Network.";             } else if (jqXHR.status == 404) {                 msg = `<div class = "alert alert-danger">Requested page not found.</div>`;             } else if (jqXHR.status == 500) {                 msg = "Internal Server Error [500].";             } else if (exception === "parsererror") {                 msg = "Requested JSON parse failed.";             } else if (exception === "timeout") {                 msg = "Time out error.";             } else if (exception === "abort") {                 msg = "Ajax request aborted.";             }             $("#alert").html(msg);
              setTimeout(() => {                 $("#123").html("");                 $("#alert").html("");                 $("profile").html("");             }, 3000);         },
                   success: function (res) {             let output = "";
              res.forEach(function (re) {                 output += `         <div class="card card-body mb-2">           <div class="row">             <div class="col-md-6">               <a href="${re.profile}" target="_blank">${re.name}</a>             </div>             <div class="col-md-6">             <span class="badge badge-primary">Stars: ${re.stargazers_count}</span>             <span class="badge badge-secondary">Watchers: ${re.watchers_count}</span>             <span class="badge badge-success">Forks: ${re.forks_count}</span>             </div>           </div>         </div>       `;             });
                           $("#123").html(output);         },     }); }
 
  function pushElToProfile(obj) {     let profile = `<div id="profile">             <div class="card card-body mb-3">                 <div class="row">                     <div class="col-md-3">                         <img class="img-fluid mb-2" src="${obj.avatar_url}">                         <a href="${obj.profile_url}" target="_blank" class="btn btn-primary btn-block mb-4">View                             Profile</a>                     </div>                     <div class="col-md-9">                         <span class="badge badge-primary">Public Repos: ${obj.public_repos}</span>                         <span class="badge badge-secondary">Public Gists: ${obj.public_gists}</span>                         <span class="badge badge-success">Followers: ${obj.followers}</span>                         <span class="badge badge-info">Following: ${obj.following}</span>                         <br><br>                         <ul class="list-group">                             <li class="list-group-item">Company: ${obj.company}</li>                             <li class="list-group-item">Website/Blog: ${obj.blog}</li>                             <li class="list-group-item">Location: ${obj.location}</li>                             <li class="list-group-item">Member Since: ${obj.create_at}</li>                         </ul>                     </div>                 </div>             </div>`;
      $("#profile").html(profile); }
 
 
  |